home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*
- * dnbglx.c : a mixed model (GL & Xlib) dial-and-button box program.
- * imitates behavior of the Dial & Button Confidence Test
- * accessible via the System Manager toolchest.
- *
- * This program creates 2 mixed model GL windows placed side-by-side:
- * 1. a singlebuffer'd GLX window is used to draw the buttons and
- * the text area (where animation is not necessary),
- * 2. a doublebuffer'd GLX window draws the dials (smooth animation
- * *is* needed here).
- *
- * There are 2 functions prior to the infinite loop that bear studying:
- *
- * 1. openwindow() sets up the X parent (including telling the WM what
- * attributes and constraints we'd like to have), the two GLX
- * children, specifies what events each window is interested in,
- * loads the correct colormaps and then maps all three windows
- * (they will not become visible however until the first expose
- * events are generated/processed).
- *
- * 2. setupdevs() finds, opens, and creates a handle to the
- * "dial+buttons" device structure. it then determines the given
- * type and class of each device event we're going to be interested
- * in, and then makes requests to the server to send us events that
- * match the events and devices described by the event list *and*
- * that come from our specific window.
- *
- * NOTE: the functionality of the GL routine SETVALUATOR(3G) (assign
- * an initial value *and* range to a valuator) is not currently
- * implemented in any X input extension from MIT. Hence, for
- * the time being in this mixed-model imitation of the pure GL
- * dial and buttons confidence test, the dial valuator's are
- * NOT constrained in their range to only [0..1023]. This is
- * the only known discrepancy between this program and the
- * original. (There is a proposal to add this extension
- * currently being debated but it is not finalized yet.)
- *
- * Following this, the get/process input infinite loop occupies the
- * rest of the program's energies. the core of this is the "default"
- * portion of the "switch (event.type)" statement which catches the
- * dial and button events being generated. notice this is where the
- * {DnB_motion_type, DnB_press_type, DnB_release_type} vars come into
- * play: recall these were defined in setupdevs() with the 3 macros
- * DeviceMotionNotify, DeviceButtonPress, and DeviceButtonRelease,
- * respectively. XSelectExtensionEvent then was used to ask the
- * server to send us any events generated by these devices in our
- * window.
- *
- * ratmandu -- november 1991
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
- #include <X11/Xos.h>
- #include <X11/Xatom.h>
- #include <X11/extensions/XI.h>
- #include <X11/extensions/XInput.h>
- #include <gl/glws.h>
- #include <gl/gl.h>
-
- /* specify window's "unresize-able" dimensions */
- #define XSIZE 840
- #define YSIZE 480
-
- #define NumButtons 32
- #define NumDials 8
-
- #define SWITCH_OFF 0
- #define SWITCH_ON 1
-
- #define top 0 /* the X parent window */
- #define SBglwin 1 /* the "buttons" are drawn in a singlebuffered win */
- #define DBglwin 2 /* and the "dials" are drawn in a doublebuffer one */
- #define MAXWINS 3
-
- typedef struct { /* struct for each button's bottom-left origin */
- Coord xpos; /* (i.e. position), and whether its being pressed */
- Coord ypos;
- int state;
- } DB_BUTTON;
-
- DB_BUTTON but[] = { /* the button's initialized values array */
- 11.0, 31.0, SWITCH_OFF,
- 16.0, 31.0, SWITCH_OFF,
- 21.0, 31.0, SWITCH_OFF,
- 26.0, 31.0, SWITCH_OFF,
- 6.0, 26.0, SWITCH_OFF,
- 11.0, 26.0, SWITCH_OFF,
- 16.0, 26.0, SWITCH_OFF,
- 21.0, 26.0, SWITCH_OFF,
- 26.0, 26.0, SWITCH_OFF,
- 31.0, 26.0, SWITCH_OFF,
- 6.0, 21.0, SWITCH_OFF,
- 11.0, 21.0, SWITCH_OFF,
- 16.0, 21.0, SWITCH_OFF,
- 21.0, 21.0, SWITCH_OFF,
- 26.0, 21.0, SWITCH_OFF,
- 31.0, 21.0, SWITCH_OFF,
- 6.0, 16.0, SWITCH_OFF,
- 11.0, 16.0, SWITCH_OFF,
- 16.0, 16.0, SWITCH_OFF,
- 21.0, 16.0, SWITCH_OFF,
- 26.0, 16.0, SWITCH_OFF,
- 31.0, 16.0, SWITCH_OFF,
- 6.0, 11.0, SWITCH_OFF,
- 11.0, 11.0, SWITCH_OFF,
- 16.0, 11.0, SWITCH_OFF,
- 21.0, 11.0, SWITCH_OFF,
- 26.0, 11.0, SWITCH_OFF,
- 31.0, 11.0, SWITCH_OFF,
- 11.0, 6.0, SWITCH_OFF,
- 16.0, 6.0, SWITCH_OFF,
- 21.0, 6.0, SWITCH_OFF,
- 26.0, 6.0, SWITCH_OFF,
- };
-
- typedef struct { /* struct for each dial's center point and */
- Coord xcntr; /* current angle value (0 is 12 o'clock) */
- Coord ycntr;
- int angle;
- } DB_DIAL;
-
- DB_DIAL dia[] = { /* the dial's initialized values array */
- 10.0, 8.0, 0,
- 20.0, 8.0, 0,
- 10.0, 15.0, 0,
- 20.0, 15.0, 0,
- 10.0, 22.0, 0,
- 20.0, 22.0, 0,
- 10.0, 29.0, 0,
- 20.0, 29.0, 0,
- };
-
- /* function declarations */
- static void openwindow(char *);
- static void setupdevs(int *, int *, int *);
- static Window glx_create_window(Window, int, int, int, int, int, char *);
- static void makeSBwin(), makeDBwin(), draw_dial(int), draw_button(int, int);
- static void clean_exit();
- static void Winset(Window, const int);
-
-
- static Display *dpy; /* X server connection */
- static Atom del_atom; /* WM_DELETE_WINDOW atom */
- static Window wins[MAXWINS]; /* holds X parent & 2 GL window handles */
-
- /* dial and buttons device event handles */
- int DnB_device_id; /* device handles for the */
- int DnB_press_type; /* DnB id, and the press, */
- int DnB_release_type; /* release, & motion */
- int DnB_motion_type; /* events they'll generate */
-
- short firstdialtouched = FALSE; /* used so text for dial valuators */
- /* doesn't get drawn until the dials */
- /* actually are turned */
-
- int myExpose; /* needs to be global for makeDBwin */
- int dialaxis[NumDials]; /* tells which dial(s) is(are) currently active */
-
-
- main(int argc, char *argv[])
- {
- int myConfigure, myMotion,
- myButtPress, myButtRelease; /* track which events occur */
- int buttP[NumButtons], buttR[NumButtons]; /* track which buttons are */
- /* pressed or released */
- long i;
- long windowvisible; /* tells event handler whether or not window */
- /* is iconified--when it is, we don't want */
- /* to process any incoming events */
-
-
-
- myExpose = myConfigure = myMotion = myButtPress = myButtRelease = FALSE;
-
- openwindow(argv[0]); /* configure/open up the window */
-
- setupdevs(buttP, buttR, dialaxis);/* set up the dial and button boxes */
-
- /*
- * The event loop.
- */
- while (1) { /* standard logic: get event(s), process event(s) */
-
- XEvent event;
- int axis_data[6];
-
- gflush(); /* For proper DGL performance */
-
- /* this "do while" loop does the `get events' half of the "get events,
- * process events" action of the infinite while. this is to ensure
- * the event queue is always drained before the events that have come
- * in are processed.
- */
- do {
-
- XNextEvent(dpy, &event);
- switch (event.type) {
-
- /* "Expose" events are sort of like "REDRAW" in gl-speak in
- * terms of when a window becomes visible, or a previously
- * invisible part becomes visible.
- */
- case Expose:
- /* see if either or both of the GL windows needs redrawing.
- * this way if only one of the two is generating the event,
- * only it will get repainted.
- */
- for (i=1; i<MAXWINS; i++)
- if (event.xexpose.window == wins[i])
- myExpose |= (1 << (i-1));
- break;
-
-
- /* "ConfigNotify" events are like "REDRAW" in terms of changes
- * to a window's size or position. Since this prog locks
- * the window's size, ConfigureNotify will occur only when
- * the window gets moved.
- */
- case ConfigureNotify:
- myConfigure = TRUE;
- break;
-
-
- /* "ButtonRelease" detects when LEFTMOUSE (Button1) is being
- * pressed indicating its time to leave.
- */
- case ButtonRelease:
- if (event.xbutton.button == Button1)
- clean_exit();
- break;
-
-
- /* "ClientMessage" is generated if the WM itself is being
- * gunned down and sends an exit signal to any running prog.
- */
- case ClientMessage:
- if (event.xclient.data.l[0] == del_atom)
- clean_exit();
- break;
-
-
- /* "MapNotify" is generated when the window is made visible.
- */
- case MapNotify:
- windowvisible = TRUE;
- break;
-
-
- /* "UnmapNotify" is generated when the window is made "invisible"
- * --like when the window is iconified. When the window is
- * not visible (i.e. iconified), we don't want any events to
- * be processed.
- */
- case UnmapNotify:
- windowvisible = FALSE;
- break;
-
-
- /* since interest is on the dNb's, they become the default.
- */
- default:
-
- if (windowvisible) { /* only process events if win is */
- /* visible (not if it's iconified) */
-
- if (event.type == DnB_motion_type) { /* dial turned */
-
- XDeviceMotionEvent *M=(XDeviceMotionEvent *)&event;
-
- if (M->deviceid == DnB_device_id) {
- i = M->first_axis; /* save out which dial */
- dialaxis[i] = TRUE; /* mark current "axis" */
- dia[i].angle = M->axis_data[0];/* save angle */
- myMotion = TRUE; /* set motion flag */
- } else
- fprintf(stderr,"cable has been disconnected\n");
-
- } else if (event.type == DnB_press_type) {
-
- XDeviceButtonEvent *B=(XDeviceButtonEvent *)&event;
-
- if (B->deviceid == DnB_device_id) {
- buttP[B->button-1] = TRUE;/* mark cur butpres*/
- myButtPress = TRUE; /* set butpres flag */
- } else
- fprintf(stderr,"cable has been disconnected\n");
-
- } else if (event.type == DnB_release_type) {
-
- XDeviceButtonEvent *B=(XDeviceButtonEvent *)&event;
-
- if (B->deviceid == DnB_device_id) {
- buttR[B->button-1] = TRUE; /* mark cur butrel*/
- myButtRelease = TRUE; /* set butrel flag */
- } else
- fprintf(stderr,"cable has been disconnected\n");
- }
- }
- break;
-
- } /* end switch (event.type) */
-
- } while (XPending(dpy)); /* end "do { } while".
- * XPending() is like qtest()--it only
- * tells you if there're any events
- * presently in the queue. it does not
- * disturb queue's contents in any way.
- */
-
-
- /* On an "Expose" event, redraw the popped, deiconified, or exposed-by-
- * another-window-being-pushed window.
- */
- if (myExpose) {
- if (myExpose & 2) {
- Winset(wins[DBglwin], DBglwin); /* draw doublebufr'd window */
- makeDBwin();
- }
- if (myExpose & 1) {
- Winset(wins[SBglwin], SBglwin); /* draw singlebufr'd window */
- makeSBwin();
- if (myButtPress) { /* check to see if button is */
- for (i=0; i<NumButtons; i++) { /* still being pressed */
- if (buttP[i])
- draw_button(i, SWITCH_ON);/* redraw pressed but */
- }
- }
- }
- myExpose = FALSE; /* reset flag--queue now empty */
- }
-
- /* On a "ConfigureNotify" event, the "GL" window has been moved.
- */
- if (myConfigure) {
- Winset(wins[DBglwin], DBglwin); /* draw the DB win's contents */
- viewport(0, (short)(XSIZE-YSIZE), 0, (short)(YSIZE-1));
- makeDBwin();
- Winset(wins[SBglwin], SBglwin); /* draw the SB win's contents */
- viewport(0, (short)(YSIZE-1), 0, (short)(YSIZE-1));
- makeSBwin();
- if (myButtPress) { /* check to see if button is */
- for (i=0; i<NumButtons; i++) { /* still being pressed */
- if (buttP[i])
- draw_button(i, SWITCH_ON); /* redraw pressed butt */
- }
- }
- myConfigure = FALSE; /* reset flag--queue now empty */
- }
-
- /* For a motion-type event (a dial turning), update the angle values
- * of whichever dials have just be sent to the event queue.
- */
- if (myMotion) {
- Winset(wins[DBglwin], DBglwin);
- for (i=0; i<NumDials; i++) {
- firstdialtouched = TRUE; /* at this point a dial is */
- draw_dial(i); /* being turned. */
- dialaxis[i] = FALSE;
- }
- swapbuffers();
- myMotion = FALSE;
- }
-
- /* For a "button press"-type event draw whichever buttons have been
- * pressed since the last time the event queue was drained.
- */
- if (myButtPress) {
- Winset(wins[SBglwin], SBglwin);
- for (i=0; i<NumButtons; i++) {
- if (buttP[i])
- draw_button(i, SWITCH_ON); /* draw button being pressed */
- }
- }
-
- /* For a "button release"-type event draw whichever buttons (in "off"
- * position) have been released since last time the event q was drained.
- */
- if (myButtRelease) {
- Winset(wins[SBglwin], SBglwin);
- for (i=0; i<NumButtons; i++) {
- if (buttR[i]) {
- draw_button(i, SWITCH_OFF);
- buttR[i] = FALSE;
- buttP[i] = FALSE;
- }
- }
- myButtPress = FALSE;
- myButtRelease = FALSE;
- }
- }
- }
-
-
-
- #include <Xm/MwmUtil.h>
-
-
- /* openwindow -
- * establish connection to X server, get screen info, specify the
- * attributes we want the WM to try to provide, and create the GL windows
- */
- static void
- openwindow(char *progname) {
-
- int screen_num; /* X screen number */
- long xorig, yorig; /* window (upper-left) origin */
- XSizeHints Winhints; /* used to fix window size */
- Atom atomName;
- MotifWmHints mwm;
-
-
-
- /* connect to the X server and get screen info */
- if ((dpy = XOpenDisplay(NULL)) == NULL) {
- fprintf(stderr, "%s: cannot connect to X server %s\n",
- progname, XDisplayName(NULL));
- exit(1);
- }
- screen_num = DefaultScreen(dpy);
-
- /* define window (upper-left) origin coords */
- xorig = (DisplayWidth(dpy, screen_num) - XSIZE) / 2;
- yorig = (DisplayHeight(dpy, screen_num) - YSIZE) / 2;
-
- /* create top level X window which will be the parent of the 2 GL windows */
- wins[top] = XCreateSimpleWindow(dpy, RootWindow(dpy, screen_num),
- xorig, yorig, XSIZE, YSIZE, 0, 0, 0);
-
- /* specify the values for the Window Size Hints we want to enforce: this
- * window can be moved but we don't want to allow any resizing to occur.
- */
- Winhints.x = xorig; /* specify desired upper-left corner origin */
- Winhints.y = yorig; /* of window so prog will place itself */
- Winhints.width = XSIZE; /* specify desired x/y size of window */
- Winhints.height = YSIZE;
- Winhints.min_width = XSIZE; /* set min and max width and */
- Winhints.max_width = XSIZE; /* height to be the same so */
- Winhints.min_height = YSIZE; /* window cannot be resized */
- Winhints.max_height = YSIZE;
- Winhints.flags = USPosition|USSize|PMaxSize|PMinSize; /* set pert. flgs */
- XSetNormalHints(dpy, wins[top], &Winhints);
-
- /* the following, culminating with XChangeProperty, enables us to remove
- * the "[re]size" menu item from the default window menu, the "maximize"
- * control button on the window frame, and the resize handle cursors
- * that are normally available when the cursor moves into the proximity
- * of any of the window's 4 corners.
- */
- mwm.flags = MWM_HINTS_FUNCTIONS;
- /* remove the decorations from the function list we don't want to have */
- mwm.functions = MWM_FUNC_ALL | MWM_FUNC_RESIZE | MWM_FUNC_MAXIMIZE;
- mwm.decorations = 0;
- mwm.input_mode = 0;
- atomName = XInternAtom(dpy, _XA_MOTIF_WM_HINTS, False);
- XChangeProperty(dpy, wins[top], atomName, atomName, sizeof(long)*8,
- PropModeReplace, (unsigned char*) &mwm, sizeof(mwm)/sizeof(long));
-
- /* create the single-buffered (buttons/text) GL imaging window */
- if ((wins[SBglwin] = glx_create_window(wins[top], 0, 0,
- YSIZE, YSIZE,
- SBglwin, progname)) == NULL) {
- fprintf(stderr,"%s: hdw doesn't support that window type\n",progname);
- exit(1);
- }
-
- /* create the double-buffered (dials) GL imaging window */
- if ((wins[DBglwin] = glx_create_window(wins[top], YSIZE, 0,
- (XSIZE-YSIZE), YSIZE,
- DBglwin, progname)) == NULL) {
- fprintf(stderr,"%s: hdw doesn't support that window type\n",progname);
- exit(1);
- }
-
- /* define string that will show up in the window title bar (and icon) */
- XStoreName(dpy, wins[top], "dial & button box confidence test");
-
- /* express interest in events we want each window to process */
- XSelectInput(dpy, wins[top], StructureNotifyMask);
- XSelectInput(dpy, wins[SBglwin], StructureNotifyMask | ButtonPressMask |
- ButtonReleaseMask | ExposureMask);
- XSelectInput(dpy, wins[DBglwin], StructureNotifyMask | ButtonPressMask |
- ButtonReleaseMask | ExposureMask);
-
- /* express interest in WM killing this app */
- if ((del_atom = XInternAtom(dpy, "WM_DELETE_WINDOW", True)) != None)
- XSetWMProtocols(dpy, wins[top], &del_atom, 1);
-
- /* map the windows--they won't actually be made visible until we process
- * the expose events up in main's infinite loop which these calls will
- * generate.
- */
- XMapWindow(dpy, wins[DBglwin]);
- XMapWindow(dpy, wins[SBglwin]);
-
- /* ensure the GL colormap is installed for this app */
- XSetWMColormapWindows(dpy, wins[top], wins, MAXWINS);
-
- /* and now map the X parent */
- XMapWindow(dpy, wins[top]);
- }
-
-
-
- /* the next 124 lines contain the code used to create the GL rendering
- * windows, which will be the children of the X parent window created
- * at the beginning of openwindow.
- */
-
- char *typeToName[] = {
- "Colormap single buffer",
- "Colormap double buffer",
- };
-
-
- /* Dorky little helper function used to build up a GLXconfig array.
- */
- static void set_entry (GLXconfig* ptr, int b, int m, int a)
- {
- ptr->buffer = b;
- ptr->mode = m;
- ptr->arg = a;
- }
-
-
- /* glx_create_window -- Create a singlebuffered, colorindex X window
- * suitable for GL imaging.
- *
- * Parameters: parent - parent window for the GL imaging window
- * x, y - window origin relative to parent
- * w, h - window width and height
- * type - single or double -buffer specifier
- * progname - name of executable
- */
- static Window
- glx_create_window(Window parent, int x, int y, int w, int h,
- int type, char *progname)
- {
- GLXconfig params[50];
- GLXconfig *next, *retconfig;
- Colormap cmap = DefaultColormap(dpy, DefaultScreen(dpy));
- XVisualInfo* vis;
- XVisualInfo template;
- XSetWindowAttributes cwa;
- XWindowAttributes pwa;
- int i, nret;
- Window win;
-
-
- /* first build an array in "params" that describes for GLXgetconfig(3G)
- * the type of GL drawing that will be done.
- */
- next = params;
- switch (type) {
- case SBglwin:
- set_entry(next++, GLX_NORMAL, GLX_DOUBLE, FALSE);
- break;
- case DBglwin:
- set_entry(next++, GLX_NORMAL, GLX_DOUBLE, TRUE);
- break;
- }
- set_entry(next, 0, 0, 0);/* The input to GLXgetconfig is null terminated */
-
- /* Get configuration data for a window based on above parameters.
- * First we have to find out which screen the parent window is on,
- * then we can call GXLgetconfig()
- */
- XGetWindowAttributes(dpy, parent, &pwa);
- retconfig = GLXgetconfig(dpy, XScreenNumberOfScreen(pwa.screen), params);
- if (retconfig == 0) {
- printf("Sorry, can't support %s type of windows\n", typeToName[type-1]);
- exit(-1);
- }
- /* The GL sets its own X error handlers, which aren't as informative
- * when errors happen. Calling XSetErrorHandler(0) here will
- * reset back to the default Xlib version.
- */
- XSetErrorHandler(0);
-
- /* Scan through config info, pulling info we need to create a window
- * that supports the rendering mode.
- */
- for (next = retconfig; next->buffer; next++) {
- unsigned long buffer = next->buffer;
- unsigned long mode = next->mode;
- unsigned long value = next->arg;
- switch (mode) {
- case GLX_COLORMAP:
- if (buffer == GLX_NORMAL) {
- cmap = value;
- }
- break;
- case GLX_VISUAL:
- if (buffer == GLX_NORMAL) {
- template.visualid = value;
- template.screen = DefaultScreen(dpy);
- vis = XGetVisualInfo(dpy, VisualScreenMask|VisualIDMask,
- &template, &nret);
- }
- break;
- }
- }
-
- /* Create the window */
- cwa.colormap = cmap;
- cwa.border_pixel = 0;
- win = XCreateWindow(dpy,parent,x,y,w,h,0,vis->depth,
- InputOutput,vis->visual,CWColormap|CWBorderPixel,&cwa);
-
- /* now rescan configuration info, find the window slot GLXgetconfig
- * provided and fill it in with the window we just created.
- */
- for (next = retconfig; next->buffer; next++) {
- if ((next->buffer == GLX_NORMAL) && (next->mode == GLX_WINDOW)) {
- next->arg = win;
- break;
- }
- }
-
- /* link to the GL */
- if ((i = GLXlink(dpy, retconfig)) < 0) {
- fprintf(stderr, "GLXlink returned %d for the %s window\n",
- i, typeToName[type-1]);
- exit(-1);
- }
-
- return win;
- }
-
-
-
- /* setupdevs -
- *
- * establish a live connection to the dial+buttons device.
- *
- * leverages off the "X11 Input Extension Library Specification"
- * document (you *shud* be able to locate the on-line public access
- * directory which contains all the files to print hard-copy of this
- * document under .../mit/doc/extensions/xinput). refer to
- * /usr/include/X11/extensions/{XI.h, XInput.h} for structures accessed.
- */
- static void
- setupdevs(int buttP[NumButtons], int buttR[NumButtons], int dialaxis[NumDials])
- {
-
- int i, ndevices;
- XDevice *DnB_device;
- XDeviceInfoPtr lp, list;
- int num_ext_event_classes;
- XEventClass ListOfEventClass[3];
- int DnB_press_class, DnB_release_class, DnB_motion_class;
-
-
- /* get a ptr to the list of all currently defined input devices */
- list = (XDeviceInfoPtr) XListInputDevices(dpy, &ndevices);
- if (!list) {
- fprintf(stderr,"XlistInputDevices failed to generate a devices list\n");
- exit(1);
- }
-
- /* check out the /usr/people/4Dgifts/examples/devices/input/X/Xlist.c
- * program (which gets compiled into "xlist"). running it will list
- * all the currently available input devices on the machine xlist is
- * run on. there is a LOT that should be studied in the "input" subtree.
- */
- for (lp=list, i=0; i<ndevices; lp++, i++) {
- if (lp->use==IsXExtensionDevice && strcmp(lp->name,"dial+buttons")==0) {
- break; /* found the right one--now save the ptr (lp) to it */
- }
- }
- if (i == ndevices) {
- fprintf(stderr, "\"dial+buttons\" device was not found\n");
- exit(1);
- }
- DnB_device = XOpenDevice(dpy, lp->id); /* open the DnB device */
- if (!DnB_device) {
- fprintf(stderr, "XOpenDevice failed for \"dial+buttons\" device\n");
- exit(1);
- }
- DnB_device_id = DnB_device->device_id; /* save out the device id */
-
- /* the following 3 macros determine the given event's type and class.
- * each macro is passed the structure that describes the device from
- * which input is desired.
- */
- DeviceButtonPress(DnB_device, DnB_press_type, DnB_press_class);
- DeviceButtonRelease(DnB_device, DnB_release_type, DnB_release_class);
- DeviceMotionNotify(DnB_device, DnB_motion_type, DnB_motion_class);
-
- ListOfEventClass[0] = DnB_press_class;
- ListOfEventClass[1] = DnB_release_class;
- ListOfEventClass[2] = DnB_motion_class;
-
- num_ext_event_classes = 3;
-
- /* XSelectExtensionEvent requests the server to send events that match
- * the events and devices described by the event list and that come
- * from the requested window.
- * first, we'll put in our button press/release requests for the
- * single-buffered (buttons and text) GL window.
- */
- XSelectExtensionEvent(dpy, wins[SBglwin],
- ListOfEventClass, num_ext_event_classes);
-
- /* now we'll request the Motion events for the double-buffered (dials)
- * GL window.
- * note that in each of these two invocations of XSelectExtensionEvent,
- * we're selecting all three event classes in each window. this is
- * because, no matter where the cursor is inside the window containing
- * both the single and double -buffered GL windows, we want to process
- * dial or button events, whether or not the mouse is physically
- * present in either of these two respective windows.
- */
- XSelectExtensionEvent(dpy, wins[DBglwin],
- ListOfEventClass, num_ext_event_classes);
-
- /* initialize all the buttons and dial "markers" to indicate none have
- * yet been pressed or moved.
- */
- for (i=0; i<NumButtons; i++) {
- buttP[i]=FALSE;
- buttR[i]=FALSE;
- }
- for (i=0; i<NumDials; i++) {
- dialaxis[i]=FALSE;
- }
- }
-
-
-
- /* A little helper wrapper for GLXwinset.
- * It passes the global variable "dpy" which contains the display, and it
- * checks the return value. This makes the call to begin GL drawing a
- * little simpler. Building in such automatic error checking is always a
- * "smooth move" (*not* like the cancerously-mutant human with the big
- * proboscis who is plastered all over the place urging people to be
- * likewise smoothly cancerous and hardly cool...).
- */
- static void Winset(Window w, const int type)
- {
- int rv = GLXwinset(dpy, w);
- if (rv < 0) {
- fprintf(stderr, "GLXWinset returned %d\ for the %s window\n",
- rv, typeToName[type-1]);
- exit(-1);
- }
- }
-
-
-
- /* makeSBwin -- Draw the buttons' and text's singlebuffer'd GL window
- */
- static void
- makeSBwin()
- {
- int i;
-
-
- if (!firstdialtouched)
- ortho2(0.0, 40.0, 0.0, 40.0);
-
- color(WHITE);
- clear();
-
- for (i=0; i<NumButtons; i++)
- draw_button(i, SWITCH_OFF); /* draw the buttons */
-
- color(BLACK);
- cmov2i(2,1);
- charstr("Use left mouse button to quit.");
-
- }
-
-
-
- /* makeDBwin -- Draw the dials' doublebuffer'd GL window
- */
- static void
- makeDBwin()
- {
- int i;
-
-
- if (myExpose) /* if we're coming thru the first time */
- frontbuffer(TRUE); /* write into (initialize) both buffers */
-
- if (!firstdialtouched)
- ortho2(0.0, 30.0, 0.0, 40.0);
-
- color(WHITE);
- clear();
-
- for (i=0; i<NumDials; i++)
- draw_dial(i); /* and draw the dials */
-
- swapbuffers();
-
- if (myExpose)
- frontbuffer(FALSE);
- }
-
-
-
-
-
-
- /* draw_dial -- Draw dial number dialno ([0..7])
- */
- static void
- draw_dial(int dialnum)
- {
- DB_DIAL *dptr = &dia[dialnum];
- Coord xcenter, ycenter;
- long angle;
- char str[80];
-
-
- xcenter = dptr->xcntr;
- ycenter = dptr->ycntr;
- angle = dptr->angle;
-
- if ((firstdialtouched) && /* when we know a dial has */
- (dialaxis[dialnum])) { /* actually been turned, update */
- Winset(wins[SBglwin], SBglwin); /* the text area and the old- */
- color(WHITE); /* sytle buttons box text-display */
- rectf(2,2,24,5);
- sprintf(str,"Dial %d intensity is %d",dialnum,angle);
- cmov2i(2,3);
- color(BLUE);
- charstr(str);
- Winset(wins[DBglwin], DBglwin);
- sprintf(str, "DIAL %d", dialnum);
- dbtext(str);
- }
-
- angle = (dptr->angle * 3600) >> 10;
- color(WHITE);
- circf(xcenter, ycenter, 2.5);
- color(BLACK);
- circ(xcenter, ycenter, 2.5);
- color(RED);
- arcf(xcenter, ycenter, 2.5, 900-angle, 900);
- }
-
-
-
- #define BSIZE 3.0
-
- /* draw_button -- Draw button number buttno in its on or off state
- */
- static void
- draw_button(int buttno, int state)
- {
- DB_BUTTON *bptr = &but[buttno];
- unsigned long button_led = 0;
- Coord xpos, ypos;
- char str[80];
-
-
- xpos = bptr->xpos;
- ypos = bptr->ypos;
-
- if (state == SWITCH_ON) {
- color(WHITE); /* make sure the correct buttons */
- rectf(2,2,24,5); /* box led (old models) lights up */
- button_led |= (1 << buttno);
- setdblights(button_led);
-
- cmov2i(2,3); /* update the text string in the */
- color(BLUE); /* bottom-left corner of the win */
- sprintf(str, "Button %d is being pressed", buttno);
- charstr(str);
-
- sprintf(str, "BUT %d", buttno); /* update the buttons box (old */
- dbtext(str); /* models) text display */
-
- color(RED); /* draw the current button red */
- rectf(xpos, ypos, xpos+BSIZE, ypos+BSIZE);
-
- } else {
- button_led &= ~(1 << buttno);
- setdblights(button_led);
- color(WHITE);
- rectf(2,2,24,5);
- rectf(xpos, ypos, xpos+BSIZE, ypos+BSIZE);
- color(BLACK);
- rect(xpos, ypos, xpos+BSIZE, ypos+BSIZE);
- }
-
- }
-
-
-
- /* clean_exit -- Clean up before exiting
- */
- static void
- clean_exit(void)
- {
- XCloseDisplay(dpy);
- exit(0);
- }
-